//
//  JukeAudioPlayer.swift
//  Aiwei
//
//  Created by zhu xietong on 2018/1/4.
//  Copyright © 2018年 zhu xietong. All rights reserved.
//

import Foundation
import Eelay

extension Jukebox.State:NotifyType
{
    public var name: Notification.Name{
        return "Jukebox.State.NotifyType.\(self.description)".notice_name
    }
}


public enum EeAudioPlayStatus:String,NotifyType{
    case ready = "ready"
    case playing = "playing"
    case paused = "paused"
    case loading = "loading"
    case failed = "failed"
    
    public var name: Notification.Name{
        return "EeAudioPlayStatus.\(EeAudioPlayStatus.self)\(self.rawValue)".notice_name
    }
}


public struct EeAudioItem{
    public var url:String
    public var cover:String
    public var name:String
}

open class EeAudioManager {
    
    public static var __shared:EeAudioManager? = nil

    public static var shared:EeAudioManager{
        get{
            guard let s = EeAudioManager.__shared else {
                let _s = EeAudioManager()
                EeAudioManager.__shared = _s
                return _s
            }
            return s
        }
    }
    
    open var jukebox :Jukebox{
        get{
            return EeAudioPlayer.sharedBox
        }
    }
    
    open var items:[EeAudioItem] = [EeAudioItem]()
    
    open var currentItem:EeAudioItem?{
        get{
            var _item:EeAudioItem? = nil
            if let item = jukebox.currentItem
            {
                for one in items
                {
                    if item.URL.path == one.url{
                        _item = one
                    }
                }
            }
            return _item
        }
    }
    
    @discardableResult
    public func add(_ item:EeAudioItem)->(index:Int,exist:Bool) {
        var i:Int = 0
        var index:Int = items.count
        
        var exist = false
        for one in items
        {
            if one.url == item.url
            {
                index = i
                exist = true
                break
            }
            i = i + 1
        }
        if !exist{
            items.append(item)
            weak var wself = self
            let delay = DispatchTime.now() + Double(Int64(0.05 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
            
            
            DispatchQueue.main.asyncAfter(deadline: delay) {
                if item.url.hasPrefix("http"){
                    if let url = URL(string:item.url)
                    {
                        let item = JukeboxItem(URL: url)
                        wself?.jukebox.append(item: item, loadingAssets: true)
                    }
                }else{
                    
                    let item = JukeboxItem(URL: URL(fileURLWithPath: item.url))
                    wself?.jukebox.append(item: item, loadingAssets: true)
                    
                }
            }
        }
        return (index,exist)
        
    }
    
}



extension EeAudioPlayer{
    
    @objc public func volumeSliderValueChanged() {
        jukebox.volume = volumeSlider.value
    }
    
    @objc public func progressSliderValueChanged() {
        if let duration = jukebox.currentItem?.meta.duration {
            jukebox.seek(toSecond: Int(Double(slider.value) * duration))
        }
    }
    
    @objc public func prevAction() {
        
        if let time = jukebox.currentItem?.currentTime, time > 5.0 || jukebox.playIndex == 0 {
            jukebox.replayCurrentItem()
        } else {
            jukebox.playPrevious()
        }
    }
    
    @objc public func nextAction() {
        jukebox.playNext()
    }
    
    @objc public func playPauseAction() {
        switch jukebox.state {
        case .ready:
            jukebox.play(atIndex: 0)
        case .playing:
            jukebox.pause()
        case .paused:
            jukebox.play()
        default:
            jukebox.stop()
        }
    }
    
    @objc public func replayAction() {
        resetUI()
        jukebox.replay()
        
    }
    
    @objc public func stopAction() {
        resetUI()
        jukebox.stop()
    }
}



open class EeAudioPlayer:JoView{
    
    
    public let slider: UISlider = UISlider()
    public let playPauseButton = UIButton()
    public let replayButton = UIButton()
    public let stopButton = UIButton()
    public let currentTimeLabel = UILabel()
    public let durationLabel = UILabel()
    public let volumeSlider = UISlider()
    public let titleLabel = UILabel()
    public let centerContainer = EeAudioDiskView.global
    public let indicator = UIActivityIndicatorView()
    
    
    public var currentPlayPercentage:CGFloat = 0.0
    
    static var __shared:EeAudioPlayer? = nil

    
    public static var shared:EeAudioPlayer{
        get{
            guard let s = EeAudioPlayer.__shared else{
                let _s = EeAudioPlayer()
                EeAudioPlayer.__shared = _s
                return _s
            }
            return s
        }
    }
    
    @objc open func doPause() {
        jukebox.pause()
    }
    
    @objc open func doPlay() {

        jukebox.play()
    }
    
    override open func addLayoutRules() {
        
//        NotificationCenter.default.addObserver(self, selector: #selector(doPause), name: "XLVideoPlayer.pause".notice_name, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(doPause), name: "XLVideoPlayer.play".notice_name, object: nil)

        
        let blur = UIBlurEffect(style: .light)
        let blurV = UIVisualEffectView(effect: blur)
        eelay = [
            [blurV,[ee.T.L.B.R]],
            [centerContainer,[ee.X.Y,[0,0]],100,"100"],
            [slider,[centerContainer,ee.B,ee.T,16],[centerContainer,ee.L.R,[-36,36]],"2"],
            [currentTimeLabel,[slider,ee.L.Y,ee.R.Y,[-4,0]],46],
            [durationLabel,[slider,ee.R.Y,ee.L.Y,[4,0]],46],
//            [playPauseButton,[ee.X],[slider,ee.B,ee.T,20],"50",50],
        ]
        
        centerContainer.eelay = [
            [playPauseButton,[ee.X.Y],"100",100],
        ]
        
        playPauseButton.contentEdgeInsets = UIEdgeInsets(top: 40, left: 40, bottom: 40, right: 40)
        
        _ = currentTimeLabel.ui.font12.cl_fff.center
        _ = durationLabel.ui.font12.cl_fff.center

        centerContainer.eelay = [
            [indicator,[ee.X.Y]],
        ]
//        centerContainer.backgroundColor = .white
        
        let nimg = UIImage(named: "audio_play", in: Bundle(for: EeAudioPlayer.self), compatibleWith: nil)
        let simg = UIImage(named: "audio_pause", in: Bundle(for: EeAudioPlayer.self), compatibleWith: nil)

        playPauseButton.ui.nimage(nimg).simage(simg)
        playPauseButton.addTarget(self, action: #selector(playPauseAction), for: .touchUpInside)
//        playPauseButton.addTarget(self, action: #selector(playOne), for: .touchUpInside)
//        let item = EeAudioItem(url: "http://220.165.14.172/mp3.9ku.com/mp3/562/561078.mp3", cover: "", name: "")
//        EeAudioManager.shared.add(item)
        configureUI()
        weak var wself = self
        centerContainer.rotationBlock = {
            degree,status in
            wself?.senderToObserver(degree: degree, status: status)
        }
    }
    open func senderToObserver(degree:CGFloat,status:EeRotationStatus) {
        for one in EeAudioDiskView.global.observers
        {
            if let url = jukebox.currentItem?.URL.absoluteString
            {
                one?.observerDisk(url: url, degree: degree, status: status, complete: self.currentPlayPercentage)
            }
        }
    }
    
    open func resetUI()
    {
        durationLabel.text = "00:00"
        currentTimeLabel.text = "00:00"
        slider.value = 0
        centerContainer.status = .end
    }
    
    open func populateLabelWithTime(_ label : UILabel, time: Double) {
        let minutes = Int(time / 60)
        let seconds = Int(time) - minutes * 60
        
        label.text = String(format: "%02d", minutes) + ":" + String(format: "%02d", seconds)
    }
    
    
    
//    @objc func playOne() {
//        let item = EeAudioItem(url: "http://220.165.14.172/mp3.9ku.com/mp3/562/561078.mp3", cover: "", name: "")
//        play(item: item)
//    }
    
    open func play(item:EeAudioItem) {
        let info = EeAudioManager.shared.add(item)
        playAudio(index: info.index,item:item)
        
    }
    
    open func updateCover() {
        centerContainer.imgV.img_url = EeAudioManager.shared.currentItem?.cover ?? ""
    }
    
    open func playAudio(index:Int,item:EeAudioItem) {
        centerContainer.status = .end
        jukebox.play(atIndex: index)
        centerContainer.status = .rotationing

        weak var wself = self
        co_delay(delay: 0.05) {
            wself?.updateCover()
        }
    }
    
    
    open var jukebox:Jukebox{
        get{
            return EeAudioPlayer.sharedBox
        }
    }
    
   
    
}


extension EeAudioPlayer:JukeboxDelegate{
    
    public static var sharedBox:Jukebox = Jukebox(delegate: EeAudioPlayer.shared, items: [JukeboxItem]())!
    public func configureUI ()
    {
        resetUI()
        let color = UIColor(red:0.84, green:0.09, blue:0.1, alpha:1)
        
        indicator.color = color
        let img = UIImage(named: "audio_slider_thumb", in: Bundle(for: EeAudioPlayer.self), compatibleWith: nil)

        slider.setThumbImage(img, for: .normal)
        slider.minimumTrackTintColor = UIColor.main_color
        slider.maximumTrackTintColor = UIColor(shex:"#fff")
        slider.addTarget(self, action: #selector(progressSliderValueChanged), for: .valueChanged)
        
        volumeSlider.minimumTrackTintColor = UIColor.main_color
        volumeSlider.maximumTrackTintColor = UIColor(shex:"#cccc")
        volumeSlider.thumbTintColor = color
        
        titleLabel.textColor =  color
        
    }
    
    // MARK:- JukeboxDelegate -
    
    public func jukeboxDidLoadItem(_ jukebox: Jukebox, item: JukeboxItem) {
        print("Jukebox did load: \(item.URL.lastPathComponent)")
    }
    
    public func jukeboxPlaybackProgressDidChange(_ jukebox: Jukebox) {
        if let currentTime = jukebox.currentItem?.currentTime, let duration = jukebox.currentItem?.meta.duration {
            let value = Float(currentTime / duration)
            slider.value = value
            self.currentPlayPercentage = CGFloat(value)
            if slider.value >= 1
            {
                //完成播放
                centerContainer.status = .end
                let img = UIImage(named: "audio_play", in: Bundle(for: EeAudioPlayer.self), compatibleWith: nil)

                playPauseButton.setImage(img, for: .normal)
//                if let url = jukebox.currentItem?.URL.absoluteString
//                {
//                }

                self.senderToObserver(degree: 0.0, status: .end)
                self.stopAction()

            }
            populateLabelWithTime(currentTimeLabel, time: currentTime)
            populateLabelWithTime(durationLabel, time: duration)
        } else {
            resetUI()
        }
    }
    
    public func jukeboxStateDidChange(_ jukebox: Jukebox) {
        EeAudioFloatBar.shared.status = jukebox.state
        
        
        updateCover()
        UIView.animate(withDuration: 0.3, animations: { () -> Void in
            self.indicator.alpha = jukebox.state == .loading ? 1 : 0
            self.playPauseButton.alpha = jukebox.state == .loading ? 0 : 1
            self.playPauseButton.isEnabled = jukebox.state == .loading ? false : true
        })
        
        __post(notify: jukebox.state)
        switch jukebox.state {
        case .failed:
            centerContainer.status = .pause
        case .loading:
            break
        case .paused:
            centerContainer.status = .pause
        case .playing:
            centerContainer.status = .rotationing
        case .ready:
            centerContainer.status = .end
        }
        
        if jukebox.state == .ready {
            let img = UIImage(named: "audio_play", in: Bundle(for: EeAudioPlayer.self), compatibleWith: nil)
            playPauseButton.setImage(img, for: .normal)
        } else if jukebox.state == .loading  {
            let img = UIImage(named: "audio_pause", in: Bundle(for: EeAudioPlayer.self), compatibleWith: nil)

            playPauseButton.setImage(img, for: .normal)
        } else {
            volumeSlider.value = jukebox.volume
            let imageName: String
            switch jukebox.state {
            case .playing, .loading:
                imageName = "audio_pause"
            case .paused, .failed, .ready:
                imageName = "audio_play"
            }
            let img = UIImage(named:imageName, in: Bundle(for: EeAudioPlayer.self), compatibleWith: nil)

            playPauseButton.setImage(img, for: .normal)
        }
        print("Jukebox state changed to \(jukebox.state)")
    }
    
    public func jukeboxDidUpdateMetadata(_ jukebox: Jukebox, forItem: JukeboxItem) {
        print("Item updated:\n\(forItem)")
    }
    
    
    func indexForBoxItem(item:JukeboxItem)->Int{
        var index = -1
    
        var i = 0
        for one in jukebox.queuedItems
        {
            if one.URL.absoluteString == item.URL.absoluteString
            {
                index = 0
            }
            i = i + 1
        }
        return index
    }

  
}

